home *** CD-ROM | disk | FTP | other *** search
/ STraTOS 1997 April & May / STraTOS 1 - 1997 April & May.iso / CD01 / INTERNET / SITES / LITTLE / P3SRC.ZIP / ATARI / TORUS.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-04-25  |  17.1 KB  |  959 lines

  1. /****************************************************************************
  2. *                   torus.c
  3. *
  4. *  This module implements functions that manipulate torii.
  5. *
  6. *  This module was written by Dieter Bayer [DB].
  7. *
  8. *  from Persistence of Vision(tm) Ray Tracer
  9. *  Copyright 1996 Persistence of Vision Team
  10. *---------------------------------------------------------------------------
  11. *  NOTICE: This source code file is provided so that users may experiment
  12. *  with enhancements to POV-Ray and to port the software to platforms other
  13. *  than those supported by the POV-Ray Team.  There are strict rules under
  14. *  which you are permitted to use this file.  The rules are in the file
  15. *  named POVLEGAL.DOC which should be distributed with this file. If
  16. *  POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  17. *  Team Coordinator by leaving a message in CompuServe's Graphics Developer's
  18. *  Forum.  The latest version of POV-Ray may be found there as well.
  19. *
  20. * This program is based on the popular DKB raytracer version 2.12.
  21. * DKBTrace was originally written by David K. Buck.
  22. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  23. *
  24. *****************************************************************************/
  25.  
  26. /****************************************************************************
  27. *
  28. *  Explanation:
  29. *
  30. *  ---
  31. *
  32. *  June 1994 : Creation. [DB]
  33. *
  34. *****************************************************************************/
  35.  
  36. #include "frame.h"
  37. #include "povray.h"
  38. #include "vector.h"
  39. #include "povproto.h"
  40. #include "bbox.h"
  41. #include "polysolv.h"
  42. #include "matrices.h"
  43. #include "objects.h"
  44. #include "torus.h"
  45.  
  46.  
  47.  
  48. /*****************************************************************************
  49. * Local preprocessor defines
  50. ******************************************************************************/
  51.  
  52. /* Minimal depth for a valid intersection. */
  53.  
  54. #define DEPTH_TOLERANCE 1.0e-4
  55.  
  56. /* Tolerance used for order reduction during root finding. */
  57.  
  58. #define ROOT_TOLERANCE 1.0e-4
  59.  
  60.  
  61.  
  62. /*****************************************************************************
  63. * Static functions
  64. ******************************************************************************/
  65.  
  66. static int intersect_torus PARAMS((RAY *Ray, TORUS *Torus, DBL *Depth));
  67. static int   All_Torus_Intersections PARAMS((OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack));
  68. static int   Inside_Torus PARAMS((VECTOR point, OBJECT *Object));
  69. static void  Torus_Normal PARAMS((VECTOR Result, OBJECT *Object, INTERSECTION *Inter));
  70. static void  *Copy_Torus PARAMS((OBJECT *Object));
  71. static void  Translate_Torus PARAMS((OBJECT *Object, VECTOR Vector, TRANSFORM *Trans));
  72. static void  Rotate_Torus PARAMS((OBJECT *Object, VECTOR Vector, TRANSFORM *Trans));
  73. static void  Scale_Torus PARAMS((OBJECT *Object, VECTOR Vector, TRANSFORM *Trans));
  74. static void  Transform_Torus PARAMS((OBJECT *Object, TRANSFORM *Trans));
  75. static void  Invert_Torus PARAMS((OBJECT *Object));
  76. static void  Destroy_Torus PARAMS((OBJECT *Object));
  77.  
  78.  
  79.  
  80. /*****************************************************************************
  81. * Local variables
  82. ******************************************************************************/
  83.  
  84. static METHODS Torus_Methods =
  85. {
  86.   All_Torus_Intersections, Inside_Torus, Torus_Normal,
  87.   Copy_Torus, Translate_Torus, Rotate_Torus,
  88.   Scale_Torus, Transform_Torus, Invert_Torus, Destroy_Torus
  89. };
  90.  
  91.  
  92. /*****************************************************************************
  93. *
  94. * FUNCTION
  95. *
  96. *   All_Torus_Intersections
  97. *
  98. * INPUT
  99. *
  100. *   Object      - Object
  101. *   Ray         - Ray
  102. *   Depth_Stack - Intersection stack
  103. *   
  104. * OUTPUT
  105. *
  106. *   Depth_Stack
  107. *   
  108. * RETURNS
  109. *
  110. *   int - TRUE, if an intersection was found
  111. *   
  112. * AUTHOR
  113. *
  114. *   Dieter Bayer
  115. *   
  116. * DESCRIPTION
  117. *
  118. *   Determine ray/torus intersection and clip intersection found.
  119. *
  120. * CHANGES
  121. *
  122. *   Jun 1994 : Creation.
  123. *
  124. ******************************************************************************/
  125.  
  126. static int All_Torus_Intersections(Object, Ray, Depth_Stack)
  127. OBJECT *Object;
  128. RAY *Ray;
  129. ISTACK *Depth_Stack;
  130. {
  131.   int i, max_i, Found;
  132.   DBL Depth[4];
  133.   VECTOR IPoint;
  134.  
  135.   Found = FALSE;
  136.  
  137.   if ((max_i = intersect_torus(Ray, (TORUS *)Object, Depth)) > 0)
  138.   {
  139.     for (i = 0; i < max_i; i++)
  140.     {
  141.       if ((Depth[i] > DEPTH_TOLERANCE) && (Depth[i] < Max_Distance))
  142.       {
  143.         VEvaluateRay(IPoint, Ray->Initial, Depth[i], Ray->Direction);
  144.  
  145.         if (Point_In_Clip(IPoint, Object->Clip))
  146.         {
  147.           push_entry(Depth[i], IPoint, Object, Depth_Stack);
  148.  
  149.           Found = TRUE;
  150.         }
  151.       }
  152.     }
  153.   }
  154.  
  155.   return(Found);
  156. }
  157.  
  158.  
  159.  
  160. /*****************************************************************************
  161. *
  162. * FUNCTION
  163. *
  164. *   intersect_torus
  165. *
  166. * INPUT
  167. *
  168. *   Ray   - Ray
  169. *   Torus - Torus
  170. *   Depth - Intersections found
  171. *   
  172. * OUTPUT
  173. *
  174. *   Depth
  175. *   
  176. * RETURNS
  177. *
  178. *   int - Number of intersections found
  179. *   
  180. * AUTHOR
  181. *
  182. *   Dieter Bayer
  183. *   
  184. * DESCRIPTION
  185. *
  186. *   Determine ray/torus intersection.
  187. *
  188. *   Note that the torus is rotated about the y-axis!
  189. *
  190. * CHANGES
  191. *
  192. *   Jun 1994 : Creation.
  193. *
  194. ******************************************************************************/
  195.  
  196. static int intersect_torus(Ray, Torus, Depth)
  197. RAY *Ray;
  198. TORUS *Torus;
  199. DBL *Depth;
  200. {
  201.   int i, n;
  202.   DBL len, R2, Py2, Dy2, PDy2, k1, k2;
  203.   DBL y1, y2, r1, r2;
  204.   DBL c[5], r[4];
  205.   VECTOR P, D;
  206.  
  207.   Increase_Counter(stats[Ray_Torus_Tests]);
  208.  
  209.   /* Transform the ray into the torus space. */
  210.  
  211.   MInvTransPoint(P, Ray->Initial, Torus->Trans);
  212.  
  213.   MInvTransDirection(D, Ray->Direction, Torus->Trans);
  214.  
  215.   VLength(len, D);
  216.  
  217.   VInverseScaleEq(D, len);
  218.  
  219.   i = 0;
  220.  
  221.   y1 = -Torus->r;
  222.   y2 =  Torus->r;
  223.   r1 = Sqr(Torus->R - Torus->r);
  224.   r2 = Sqr(Torus->R + Torus->r);
  225.  
  226. #ifdef TORUS_EXTRA_STATS
  227.   Increase_Counter(stats[Torus_Bound_Tests]);
  228. #endif
  229.  
  230.   if (Test_Thick_Cylinder(P, D, y1, y2, r1, r2))
  231.   {
  232. #ifdef TORUS_EXTRA_STATS
  233.     Increase_Counter(stats[Torus_Bound_Tests_Succeeded]);
  234. #endif
  235.  
  236.     R2   = Sqr(Torus->R);
  237.     r2   = Sqr(Torus->r);
  238.  
  239.     Py2  = P[Y] * P[Y];
  240.     Dy2  = D[Y] * D[Y];
  241.     PDy2 = P[Y] * D[Y];
  242.  
  243.     k1   = P[X] * P[X] + P[Z] * P[Z] + Py2 - R2 - r2;
  244.     k2   = P[X] * D[X] + P[Z] * D[Z] + PDy2;
  245.  
  246.     c[0] = 1.0;
  247.  
  248.     c[1] = 4.0 * k2;
  249.  
  250.     c[2] = 2.0 * (k1 + 2.0 * (k2 * k2 + R2 * Dy2));
  251.  
  252.     c[3] = 4.0 * (k2 * k1 + 2.0 * R2 * PDy2);
  253.  
  254.     c[4] = k1 * k1 + 4.0 * R2 * (Py2 - r2);
  255.  
  256.     n = Solve_Polynomial(4, c, r, Test_Flag(Torus, STURM_FLAG), ROOT_TOLERANCE);
  257.  
  258.     while(n--)
  259.     {
  260.       Depth[i++] = r[n] / len;
  261.     }
  262.   }
  263.  
  264.   if (i)
  265.   {
  266.     Increase_Counter(stats[Ray_Torus_Tests_Succeeded]);
  267.   }
  268.  
  269.   return(i);
  270. }
  271.  
  272.  
  273.  
  274. /*****************************************************************************
  275. *
  276. * FUNCTION
  277. *
  278. *   Inside_Torus
  279. *
  280. * INPUT
  281. *
  282. *   IPoint - Intersection point
  283. *   Object - Object
  284. *   
  285. * OUTPUT
  286. *   
  287. * RETURNS
  288. *
  289. *   int - TRUE if inside
  290. *   
  291. * AUTHOR
  292. *
  293. *   Dieter Bayer
  294. *   
  295. * DESCRIPTION
  296. *
  297. *   Test if a point lies inside the torus.
  298. *
  299. * CHANGES
  300. *
  301. *   Jun 1994 : Creation.
  302. *
  303. ******************************************************************************/
  304.  
  305. static int Inside_Torus(IPoint, Object)
  306. VECTOR IPoint;
  307. OBJECT *Object;
  308. {
  309.   DBL r, r2;
  310.   VECTOR P;
  311.   TORUS *Torus = (TORUS *)Object;
  312.  
  313.   /* Transform the point into the torus space. */
  314.  
  315.   MInvTransPoint(P, IPoint, Torus->Trans);
  316.  
  317.   r  = sqrt(Sqr(P[X]) + Sqr(P[Z]));
  318.  
  319.   r2 = Sqr(P[Y]) + Sqr(r - Torus->R);
  320.  
  321.   if (r2 <= Sqr(Torus->r))
  322.   {
  323.     return(!Test_Flag(Torus, INVERTED_FLAG));
  324.   }
  325.   else
  326.   {
  327.     return(Test_Flag(Torus, INVERTED_FLAG));
  328.   }
  329. }
  330.  
  331.  
  332.  
  333. /*****************************************************************************
  334. *
  335. * FUNCTION
  336. *
  337. *   Torus_Normal
  338. *
  339. * INPUT
  340. *
  341. *   Result - Normal vector
  342. *   Object - Object
  343. *   Inter  - Intersection found
  344. *   
  345. * OUTPUT
  346. *
  347. *   Result
  348. *   
  349. * RETURNS
  350. *   
  351. * AUTHOR
  352. *
  353. *   Dieter Bayer
  354. *   
  355. * DESCRIPTION
  356. *
  357. *   Calculate the normal of the torus in a given point.
  358. *
  359. * CHANGES
  360. *
  361. *   Jun 1994 : Creation.
  362. *
  363. ******************************************************************************/
  364.  
  365. static void Torus_Normal(Result, Object, Inter)
  366. OBJECT *Object;
  367. VECTOR Result;
  368. INTERSECTION *Inter;
  369. {
  370.   DBL dist;
  371.   VECTOR P, N, M;
  372.   TORUS *Torus = (TORUS *)Object;
  373.  
  374.   /* Transform the point into the torus space. */
  375.  
  376.   MInvTransPoint(P, Inter->IPoint, Torus->Trans);
  377.  
  378.   /* Get normal from derivatives. */
  379.  
  380.   dist = sqrt(P[X] * P[X] + P[Z] * P[Z]);
  381.  
  382.   if (dist > EPSILON)
  383.   {
  384.     M[X] = Torus->R * P[X] / dist;
  385.     M[Y] = 0.0;
  386.     M[Z] = Torus->R * P[Z] / dist;
  387.   }
  388.   else
  389.   {
  390.     Make_Vector(M, 0.0, 0.0, 0.0);
  391.   }
  392.  
  393.   VSub(N, P, M);
  394.  
  395.   /* Transform the normalt out of the torus space. */
  396.  
  397.   MTransNormal(Result, N, Torus->Trans);
  398.  
  399.   VNormalize(Result, Result);
  400. }
  401.  
  402.  
  403.  
  404. /*****************************************************************************
  405. *
  406. * FUNCTION
  407. *
  408. *   Translate_Torus
  409. *
  410. * INPUT
  411. *
  412. *   Object - Object
  413. *   Vector - Translation vector
  414. *   
  415. * OUTPUT
  416. *
  417. *   Object
  418. *   
  419. * RETURNS
  420. *   
  421. * AUTHOR
  422. *
  423. *   Dieter Bayer
  424. *
  425. * DESCRIPTION
  426. *
  427. *   Translate a torus.
  428. *
  429. * CHANGES
  430. *
  431. *   Jun 1994 : Creation.
  432. *
  433. ******************************************************************************/
  434.  
  435. static void Translate_Torus(Object, Vector, Trans)
  436. OBJECT *Object;
  437. VECTOR Vector;
  438. TRANSFORM *Trans;
  439. {
  440.   Transform_Torus(Object, Trans);
  441. }
  442.  
  443.  
  444.  
  445. /*****************************************************************************
  446. *
  447. * FUNCTION
  448. *
  449. *   Rotate_Torus
  450. *
  451. * INPUT
  452. *
  453. *   Object - Object
  454. *   Vector - Rotation vector
  455. *   
  456. * OUTPUT
  457. *
  458. *   Object
  459. *   
  460. * RETURNS
  461. *   
  462. * AUTHOR
  463. *
  464. *   Dieter Bayer
  465. *   
  466. * DESCRIPTION
  467. *
  468. *   Rotate a torus.
  469. *
  470. * CHANGES
  471. *
  472. *   Jun 1994 : Creation.
  473. *
  474. ******************************************************************************/
  475.  
  476. static void Rotate_Torus(Object, Vector, Trans)
  477. OBJECT *Object;
  478. VECTOR Vector;
  479. TRANSFORM *Trans;
  480. {
  481.   Transform_Torus(Object, Trans);
  482. }
  483.  
  484.  
  485.  
  486. /*****************************************************************************
  487. *
  488. * FUNCTION
  489. *
  490. *   Scale_Torus
  491. *
  492. * INPUT
  493. *
  494. *   Object - Object
  495. *   Vector - Scaling vector
  496. *   
  497. * OUTPUT
  498. *
  499. *   Object
  500. *   
  501. * RETURNS
  502. *   
  503. * AUTHOR
  504. *
  505. *   Dieter Bayer
  506. *   
  507. * DESCRIPTION
  508. *
  509. *   Scale a torus.
  510. *
  511. * CHANGES
  512. *
  513. *   Jun 1994 : Creation.
  514. *
  515. ******************************************************************************/
  516.  
  517. static void Scale_Torus(Object, Vector, Trans)
  518. OBJECT *Object;
  519. VECTOR Vector;
  520. TRANSFORM *Trans;
  521. {
  522.   Transform_Torus(Object, Trans);
  523. }
  524.  
  525.  
  526.  
  527. /*****************************************************************************
  528. *
  529. * FUNCTION
  530. *
  531. *   Transform_Torus
  532. *
  533. * INPUT
  534. *
  535. *   Object - Object
  536. *   Trans  - Transformation to apply
  537. *   
  538. * OUTPUT
  539. *
  540. *   Object
  541. *   
  542. * RETURNS
  543. *   
  544. * AUTHOR
  545. *
  546. *   Dieter Bayer
  547. *   
  548. * DESCRIPTION
  549. *
  550. *   Transform a torus and recalculate its bounding box.
  551. *
  552. * CHANGES
  553. *
  554. *   Jun 1994 : Creation.
  555. *
  556. ******************************************************************************/
  557.  
  558. static void Transform_Torus(Object, Trans)
  559. OBJECT *Object;
  560. TRANSFORM *Trans;
  561. {
  562.   Compose_Transforms(((TORUS *)Object)->Trans, Trans);
  563.  
  564.   Compute_Torus_BBox((TORUS *)Object);
  565. }
  566.  
  567.  
  568.  
  569. /*****************************************************************************
  570. *
  571. * FUNCTION
  572. *
  573. *   Invert_Torus
  574. *
  575. * INPUT
  576. *
  577. *   Object - Object
  578. *   
  579. * OUTPUT
  580. *
  581. *   Object
  582. *   
  583. * RETURNS
  584. *   
  585. * AUTHOR
  586. *
  587. *   Dieter Bayer
  588. *   
  589. * DESCRIPTION
  590. *
  591. *   Invert a torus.
  592. *
  593. * CHANGES
  594. *
  595. *   Jun 1994 : Creation.
  596. *
  597. ******************************************************************************/
  598.  
  599. static void Invert_Torus(Object)
  600. OBJECT *Object;
  601. {
  602.   Invert_Flag(Object, INVERTED_FLAG);
  603. }
  604.  
  605.  
  606.  
  607. /*****************************************************************************
  608. *
  609. * FUNCTION
  610. *
  611. *   Create_Torus
  612. *
  613. * INPUT
  614. *   
  615. * OUTPUT
  616. *   
  617. * RETURNS
  618. *
  619. *   TORUS * - new torus
  620. *   
  621. * AUTHOR
  622. *
  623. *   Dieter Bayer
  624. *   
  625. * DESCRIPTION
  626. *
  627. *   Create a new torus.
  628. *
  629. * CHANGES
  630. *
  631. *   Jun 1994 : Creation.
  632. *
  633. ******************************************************************************/
  634.  
  635. TORUS *Create_Torus()
  636. {
  637.   TORUS *New;
  638.  
  639.   New = (TORUS *)POV_MALLOC(sizeof(TORUS), "torus");
  640.  
  641.   INIT_OBJECT_FIELDS(New,TORUS_OBJECT,&Torus_Methods)
  642.  
  643.   New->Trans = Create_Transform();
  644.  
  645.   New->R =
  646.   New->r = 0.0;
  647.  
  648.   return (New);
  649. }
  650.  
  651.  
  652.  
  653. /*****************************************************************************
  654. *
  655. * FUNCTION
  656. *
  657. *   Copy_Torus
  658. *
  659. * INPUT
  660. *
  661. *   Object - Object
  662. *   
  663. * OUTPUT
  664. *   
  665. * RETURNS
  666. *
  667. *   void * - New torus
  668. *   
  669. * AUTHOR
  670. *
  671. *   Dieter Bayer
  672. *   
  673. * DESCRIPTION
  674. *
  675. *   Copy a torus.
  676. *
  677. * CHANGES
  678. *
  679. *   Jun 1994 : Creation.
  680. *
  681. *   Sep 1994 : fixed memory leakage [DB]
  682. *
  683. ******************************************************************************/
  684.  
  685. static void *Copy_Torus(Object)
  686. OBJECT *Object;
  687. {
  688.   TORUS *New, *Torus = (TORUS *)Object;
  689.  
  690.   New = Create_Torus();
  691.  
  692.   /* Get rid of the transformation created in Create_Torus(). */
  693.  
  694.   Destroy_Transform(New->Trans);
  695.  
  696.   /* Copy torus. */
  697.  
  698.   *New = *Torus;
  699.  
  700.   New->Trans = Copy_Transform(Torus->Trans);
  701.  
  702.   return (New);
  703. }
  704.  
  705.  
  706.  
  707. /*****************************************************************************
  708. *
  709. * FUNCTION
  710. *
  711. *   Destroy_Torus
  712. *
  713. * INPUT
  714. *
  715. *   Object - Object
  716. *   
  717. * OUTPUT
  718. *
  719. *   Object
  720. *   
  721. * RETURNS
  722. *   
  723. * AUTHOR
  724. *
  725. *   Dieter Bayer
  726. *   
  727. * DESCRIPTION
  728. *
  729. *   Destroy a torus.
  730. *
  731. * CHANGES
  732. *
  733. *   Jun 1994 : Creation.
  734. *
  735. ******************************************************************************/
  736.  
  737. static void Destroy_Torus (Object)
  738. OBJECT *Object;
  739. {
  740.   Destroy_Transform(((TORUS *)Object)->Trans);
  741.  
  742.   POV_FREE (Object);
  743. }
  744.  
  745.  
  746.  
  747. /*****************************************************************************
  748. *
  749. * FUNCTION
  750. *
  751. *   Compute_Torus_BBox
  752. *
  753. * INPUT
  754. *
  755. *   Torus - Torus
  756. *   
  757. * OUTPUT
  758. *
  759. *   Torus
  760. *   
  761. * RETURNS
  762. *   
  763. * AUTHOR
  764. *
  765. *   Dieter Bayer
  766. *   
  767. * DESCRIPTION
  768. *
  769. *   Calculate the bounding box of a torus.
  770. *
  771. * CHANGES
  772. *
  773. *   Jun 1994 : Creation.
  774. *
  775. ******************************************************************************/
  776.  
  777. void Compute_Torus_BBox(Torus)
  778. TORUS *Torus;
  779. {
  780.   DBL r1, r2;
  781.  
  782.   r1 = Torus->r;
  783.   r2 = Torus->R + Torus->r;
  784.  
  785.   Make_BBox(Torus->BBox, -r2, -r1, -r2, 2.0 * r2, 2.0 * r1, 2.0 * r2);
  786.  
  787.   Recompute_BBox(&Torus->BBox, Torus->Trans);
  788. }
  789.  
  790.  
  791.  
  792. /*****************************************************************************
  793. *
  794. * FUNCTION
  795. *
  796. *   Test_Thick_Cylinder
  797. *
  798. * INPUT
  799. *
  800. *   P  - Ray initial
  801. *   D  - Ray direction
  802. *   h1 - Height 1
  803. *   h2 - Height 2
  804. *   r1 - Square of inner radius
  805. *   r2 - Square of outer radius
  806. *   
  807. * OUTPUT
  808. *   
  809. * RETURNS
  810. *
  811. *   int - TRUE, if hit
  812. *   
  813. * AUTHOR
  814. *
  815. *   Dieter Bayer
  816. *   
  817. * DESCRIPTION
  818. *
  819. *   Test if a given ray defined in the lathe's coordinate system
  820. *   intersects a "thick" cylinder (rotated about y-axis).
  821. *
  822. * CHANGES
  823. *
  824. *   Jun 1994 : Creation.
  825. *
  826. ******************************************************************************/
  827.  
  828. int Test_Thick_Cylinder(P, D, h1, h2, r1, r2)
  829. VECTOR P, D;
  830. DBL h1, h2, r1, r2;
  831. {
  832.   DBL a, b, c, d;
  833.   DBL u, v, k, r, k1, k2;
  834.  
  835.   if (fabs(D[Y]) < EPSILON)
  836.   {
  837.     if ((P[Y] < h1) || (P[Y] > h2))
  838.     {
  839.       return(FALSE);
  840.     }
  841.   }
  842.   else
  843.   {
  844.     /* Intersect ray with the cap-plane. */
  845.  
  846.     k = (h2 - P[Y]) / D[Y];
  847.  
  848.     u = P[X] + k * D[X];
  849.     v = P[Z] + k * D[Z];
  850.  
  851.     if ((k > EPSILON) && (k < Max_Distance))
  852.     {
  853.       r = u * u + v * v;
  854.  
  855.       if ((r >= r1) && (r <= r2))
  856.       {
  857.         return(TRUE);
  858.       }
  859.     }
  860.  
  861.     /* Intersectionersect ray with the base-plane. */
  862.  
  863.     k = (h1 - P[Y]) / D[Y];
  864.  
  865.     u = P[X] + k * D[X];
  866.     v = P[Z] + k * D[Z];
  867.  
  868.     if ((k > EPSILON) && (k < Max_Distance))
  869.     {
  870.       r = u * u + v * v;
  871.  
  872.       if ((r >= r1) && (r <= r2))
  873.       {
  874.         return(TRUE);
  875.       }
  876.     }
  877.   }
  878.  
  879.   a = D[X] * D[X] + D[Z] * D[Z];
  880.  
  881.   if (a > EPSILON)
  882.   {
  883.     /* Intersect with outer cylinder. */
  884.  
  885.     b = P[X] * D[X] + P[Z] * D[Z];
  886.  
  887.     c = P[X] * P[X] + P[Z] * P[Z] - r2;
  888.  
  889.     d = b * b - a * c;
  890.  
  891.     if (d >= 0.0)
  892.     {
  893.       d = sqrt(d);
  894.  
  895.       k1 = (-b + d) / a;
  896.       k2 = (-b - d) / a;
  897.  
  898.       if ((k1 > EPSILON) && (k1 < Max_Distance))
  899.       {
  900.         k = P[Y] + k1 * D[Y];
  901.  
  902.         if ((k >= h1) && (k <= h2))
  903.         {
  904.           return(TRUE);
  905.         }
  906.       }
  907.  
  908.       if ((k2 > EPSILON) && (k2 < Max_Distance))
  909.       {
  910.         k = P[Y] + k2 * D[Y];
  911.  
  912.         if ((k >= h1) && (k <= h2))
  913.         {
  914.           return(TRUE);
  915.         }
  916.       }
  917.     }
  918.  
  919.     /* Intersect with inner cylinder. */
  920.  
  921.     c = P[X] * P[X] + P[Z] * P[Z] - r1;
  922.  
  923.     d = b * b - a * c;
  924.  
  925.     if (d >= 0.0)
  926.     {
  927.       d = sqrt(d);
  928.  
  929.       k1 = (-b + d) / a;
  930.       k2 = (-b - d) / a;
  931.  
  932.       if ((k1 > EPSILON) && (k1 < Max_Distance))
  933.       {
  934.         k = P[Y] + k1 * D[Y];
  935.  
  936.         if ((k >= h1) && (k <= h2))
  937.         {
  938.           return(TRUE);
  939.         }
  940.       }
  941.  
  942.       if ((k2 > EPSILON) && (k2 < Max_Distance))
  943.       {
  944.         k = P[Y] + k2 * D[Y];
  945.  
  946.         if ((k >= h1) && (k <= h2))
  947.         {
  948.           return(TRUE);
  949.         }
  950.       }
  951.     }
  952.   }
  953.  
  954.   return(FALSE);
  955. }
  956.  
  957.  
  958.  
  959.